-
Notifications
You must be signed in to change notification settings - Fork 201
Add tuple support in interactive prompts #1333
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @spalladino! The logic looks solid.
packages/lib/src/utils/ABIs.ts
Outdated
@@ -66,9 +66,17 @@ export function getABIFunction(contract: Contract, methodName: string, args: any | |||
} | |||
} | |||
|
|||
export function getABIType(arg: any): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think InputInfo
is the right type.
export function getABIType(arg: any): string { | |
export function getABIType(arg: InputInfo): string { |
Also what do you think about renaming this function so that it's clear it's for display purposes? displayABIType
, getABITypeDisplay
, getABITypeLabel
, ... Not sure. I also think it's kind of redundant for the name to say ABI
, since it's the name of the module it's contained in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point on the naming. Changed it to getArgTypeLabel
.
packages/cli/src/utils/input.ts
Outdated
@@ -238,3 +250,35 @@ export function validateSalt(salt: string, required = false) { | |||
throw new Error(`Invalid salt ${salt}, must be an uint256 value.`); | |||
} | |||
} | |||
|
|||
export function getPlaceholder(arg: Pick<MethodArg, 'type' | 'components'>): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think "placeholder" is very accurate. What about getSampleInput
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like it! The original name was placeholder because the idea was to use it as a placeholder when presenting the question, but it was after that we noted that inquirer does not support placeholders (it only displays them when they are the default value).
packages/cli/src/utils/input.ts
Outdated
@@ -46,18 +48,24 @@ function quoteArguments(args: string) { | |||
return args; | |||
} | |||
|
|||
export function parseArg(input: string | string[], type: string): any { | |||
export function parseArg(input: string | string[], { type, components }: Pick<MethodArg, 'type' | 'components'>): any { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use the entire MethodArg
type here? I imagine that using Pick
simplifies the tests? Is there another reason?
If we insist on not using the entire type, I think we should define a type alias in this file. It represents an important concept, and it's used twice in the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem was in the recursive call, since the types for an array (for example) are not named. I agree with giving it a proper name, just created MethodArgType
for that.
// TODO: Handle tuples in ABI specification | ||
// Tuples: recursively parse | ||
if (type === 'tuple') { | ||
const inputs = typeof input === 'string' ? parseArray(stripParens(input), '(', ')') : input; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it weird that parseArray
wouldn't handle the delimiters itself. What do you think about doing that?
Also, why do we allow the input to not be surrounded by delimiters? In what cases is that used? Does that apply to tuples in the same way that it applies to arrays?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it weird that parseArray wouldn't handle the delimiters itself. What do you think about doing that?
Good point, I think it could be refactored. That said, given that this routine is pretty isolated (and working!), I wouldn't risk changing it now.
Also, why do we allow the input to not be surrounded by delimiters? In what cases is that used? Does that apply to tuples in the same way that it applies to arrays?
When the user is prompted to enter an array, they can just enter a comma separated list, without the brackets, for simplicity. Same applies for tuples.
@@ -59,18 +59,20 @@ function getCommandProps( | |||
return { | |||
...accum, | |||
[arg.name]: { | |||
message: arg.name ? `${arg.name} (${arg.type}):` : `(${arg.type}):`, | |||
message: argLabel(arg), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the previous string had a colon at the end, and argLabel
doesn't (which is okay because in the other place where it's used there was no colon).
message: argLabel(arg), | |
message: argLabel(arg) + ':', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
packages/cli/src/utils/input.ts
Outdated
@@ -46,18 +48,24 @@ function quoteArguments(args: string) { | |||
return args; | |||
} | |||
|
|||
export function parseArg(input: string | string[], type: string): any { | |||
export function parseArg(input: string | string[], { type, components }: Pick<MethodArg, 'type' | 'components'>): any { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, in what cases is input
an array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, parseArray
does not parse just the top-level arrays, but it returns arrays of arrays (as many levels deep as needed). So, the parseArg
recursive call in the case of arrays may be done with an array instead of a string.
And writing this I'm thinking that maybe arrays of tuples (or viceversa) may not work...
@@ -261,8 +274,10 @@ export function getPlaceholder(type: string): string { | |||
return '0x1df62f291b2e969fb0849d99d9ce41e2f137006e'; | |||
} else if (type === 'string') { | |||
return 'Hello world'; | |||
} else if (type === 'tuple' && components) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there cases when components
is undefined?
packages/cli/src/utils/input.ts
Outdated
@@ -238,3 +250,35 @@ export function validateSalt(salt: string, required = false) { | |||
throw new Error(`Invalid salt ${salt}, must be an uint256 value.`); | |||
} | |||
} | |||
|
|||
export function getPlaceholder(arg: Pick<MethodArg, 'type' | 'components'>): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler isn't catching this because we're not running it in strict mode. It will be a bit of an undertaking to enable it, but I would highly recommend we do.
export function getPlaceholder(arg: Pick<MethodArg, 'type' | 'components'>): string { | |
export function getPlaceholder(arg: Pick<MethodArg, 'type' | 'components'>): string | null { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good one. And agree on the strict mode!
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
@frangio updated! |
packages/lib/src/utils/ABIs.ts
Outdated
@@ -137,5 +146,6 @@ export function callDescription(method: any, args: string[]): string { | |||
export default { | |||
buildCallData, | |||
getABIFunction, | |||
getABIType: getArgTypeLabel, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we remove this here? It didn't exist before this PR so there are no backwards compatibility issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that was the auto-rename backfiring - sorry about it
@frangio updated! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🚀
Fixes #1330. Tuples can be entered as comma separated, or as comma separated enclosed in parenthesis.